package com.niiwoo.civet.account.service.local.openAccount;

import com.niiwoo.civet.account.constant.AccountRegisterErrorCode;
import com.niiwoo.civet.account.dao.entity.*;
import com.niiwoo.civet.account.dto.common.LanMaoGatewayRequestDTO;
import com.niiwoo.civet.account.dto.request.CreateRegisterOrderRequestDTO;
import com.niiwoo.civet.account.enums.AccountTypeEnum;
import com.niiwoo.civet.account.enums.OpenAccountRecordStatusEnum;
import com.niiwoo.civet.account.enums.OpenAccountWayEnum;
import com.niiwoo.civet.account.service.local.AccountCompanyService;
import com.niiwoo.civet.account.service.local.AccountPersonService;
import com.niiwoo.civet.account.service.local.BankCardService;
import com.niiwoo.civet.account.service.local.OpenAccountRecordService;
import com.niiwoo.tripod.base.component.PrivacyMasks;
import com.niiwoo.tripod.lanmao.component.LanMaoDirectService;
import com.niiwoo.tripod.lanmao.component.LanMaoSequence;
import com.niiwoo.tripod.lanmao.enums.AuditTypeEnum;
import com.niiwoo.tripod.lanmao.enums.UserRoleEnum;
import com.niiwoo.tripod.lanmao.enums.UserTypeEnum;
import com.niiwoo.tripod.lanmao.response.QueryUserInformationResponse;
import com.niiwoo.tripod.provider.exception.BizException;
import com.niiwoo.tripod.service.component.SnowflakeIdWorker;
import java.util.Arrays;
import java.util.Collections;
import java.util.Date;
import java.util.HashSet;
import java.util.List;
import java.util.Optional;
import java.util.Set;
import java.util.function.Supplier;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;

@Slf4j
//@Component
public class QueryOpenAccountService extends AbstractOpenAccountService<OpenAccountRecord, OpenAccountRecordStatusEnum> {

    @Autowired
    OpenAccountTemplate openAccountTemplate;

    @Autowired
    SnowflakeIdWorker snowflakeIdWorker;

    @Autowired
    OpenAccountRecordService openAccountRecordService;

    @Autowired
    BankCardService bankCardService;

    @Autowired
    PrivacyMasks privacyMasks;

    @Autowired
    AccountPersonService accountPersonService;

    @Autowired
    AccountCompanyService accountCompanyService;

    @Autowired
    LanMaoSequence lanMaoSequence;

    @Autowired
    LanMaoDirectService lanMaoDirectService;

    @Override
    protected LanMaoGatewayRequestDTO internalCreateOrder(CreateRegisterOrderRequestDTO requestDTO) {
        throw new UnsupportedOperationException("不支持创建订单");
    }

    @Override
    public OpenAccountRecordStatusEnum updateOrder(OpenAccountRecord record) {
        String requestNo = lanMaoSequence.getRequestNo();
        QueryUserInformationResponse response = openAccountTemplate.queryLanmaoAccountStatus(record.getAccountNo(), requestNo);
        //  请求成功
        if (response.isSuccess()) {
            // 迁移导入会员状态=true， 个人和企业注册默认是true, 激活接口调用成功=true
            if (response.getIsImportUserActivate()) {
                switch (response.getAuditStatus()) {
                    // 审核通过
                    case PASSED:
                        return Optional.of(record)
                                .filter(r -> this.updateSuccessRecord(r, response))
                                .map(r -> OpenAccountRecordStatusEnum.SUCCESS)
                                .orElseThrow(() -> {
                                    log.error("懒猫接口###查询用户信息接口成功###初始化账户失败, requestNo={}, recordId={}", requestNo, record.getId());
                                    return new BizException(AccountRegisterErrorCode.INIT_ACCOUNT_FAIL);
                                });
                    // 退回
                    case BACK:
                        return Optional.of(record)
                                .filter(r -> this.doHandleUnSuccessOrder(r, OpenAccountRecordStatusEnum.AUDIT_RETURN))
                                .map(r -> OpenAccountRecordStatusEnum.AUDIT_RETURN)
                                .orElseThrow(() -> {
                                    log.error("懒猫接口###查询用户信息接口#修改开户记录为退回, requestNo={}, recordId={}", requestNo, record.getId());
                                    return new BizException(AccountRegisterErrorCode.UPDATE_RECORD_FAIL);
                                });
                    // 拒绝
                    case REFUSED:
                        return Optional.of(record)
                                .filter(r -> this.doHandleUnSuccessOrder(r, OpenAccountRecordStatusEnum.AUDIT_REJECT))
                                .map(r -> OpenAccountRecordStatusEnum.AUDIT_REJECT)
                                .orElseThrow(() -> {
                                    log.error("懒猫接口###查询用户信息接口#修改开户记录为拒绝, requestNo={}, recordId={}", requestNo, record.getId());
                                    return new BizException(AccountRegisterErrorCode.UPDATE_RECORD_FAIL);
                                });
                    // 审核中
                    case AUDIT:
                        return Optional.of(record)
                                .filter(r -> this.doHandleUnSuccessOrder(r, OpenAccountRecordStatusEnum.AUDITING))
                                .map(r -> OpenAccountRecordStatusEnum.AUDITING)
                                .orElseThrow(() -> {
                                    log.error("懒猫接口###查询用户信息接口#修改开户记录为审核中, requestNo={}, recordId={}", requestNo, record.getId());
                                    return new BizException(AccountRegisterErrorCode.UPDATE_RECORD_FAIL);
                                });
                    // 默认返回原状态
                    default:
                        return OpenAccountRecordStatusEnum.of(record.getStatus());
                }
                // 账户未激活(没有调用激活接口成功)且记录过期
            } else if (isRecordExpire(record.getLastRequestTime())) {
                return updateExpireRecord(record, requestNo, response.getAuditStatus());
            }
        } else if ("100009".equals(StringUtils.defaultIfBlank(response.getErrorCode(), "")) && isRecordExpire(record.getLastRequestTime())) {
            // 用户不存在且记录过期
            return updateExpireRecord(record, requestNo, response.getAuditStatus());
        }
        // 默认返回原状态
        return OpenAccountRecordStatusEnum.of(record.getStatus());
    }

    private OpenAccountRecordStatusEnum updateExpireRecord(OpenAccountRecord record, String requestNo, AuditTypeEnum auditStatus) {
        return Optional.of(record)
                .filter(r -> this.doHandleUnSuccessOrder(r, OpenAccountRecordStatusEnum.EXPIRED))
                .map(r -> OpenAccountRecordStatusEnum.EXPIRED)
                .orElseThrow(() -> {
                    log.error("懒猫接口###查询用户信息接口#修改开户记录为过期, requestNo={}, auditStatus={}, recordId={}", requestNo, auditStatus, record.getId());
                    return new BizException(AccountRegisterErrorCode.UPDATE_RECORD_FAIL);
                });
    }

    private boolean doHandleUnSuccessOrder(OpenAccountRecord record, OpenAccountRecordStatusEnum recordStatus) {
        return openAccountTemplate.doHandleUnSuccessOrder(record, recordStatus, null, "", "");
    }

    private boolean updateSuccessRecord(OpenAccountRecord record, QueryUserInformationResponse response) {
        Optional<AccountBase> oldBaseOpt = Optional.ofNullable(openAccountRecordService.getAccountBase(record.getUserId(), UserRoleEnum.enumOf(record.getAccountRole())));
        AccountTypeEnum accountType = response.getUserType() == UserTypeEnum.ORGANIZATION ? AccountTypeEnum.ENTERPRISE : AccountTypeEnum.PERSONAL;
        Set<String> authSet = Optional.ofNullable(response.getAuthlist())
                .map(s -> {
                    Set<String> set = new HashSet<>(Arrays.asList(s.split(",")));
                    return set;
                })
                .orElse(Collections.EMPTY_SET);
        // 账户基础信息
        AccountBase accountBase = oldBaseOpt.map(b -> AccountEntityBuilder.buildActivateAccountBase(b, authSet)).orElse(AccountEntityBuilder.buildInitAccountBase(snowflakeIdWorker.nextId(), record, accountType, authSet));
        // 账户个人/企业信息更新函数
        Supplier<Boolean> s1;
        BankCard preBankCard;
        if (accountType == AccountTypeEnum.PERSONAL) {
            preBankCard = bankCardService.getSimpleUserBankCard(record.getUserId());
            // 个人注册、激活和关联
            AccountPerson person = oldBaseOpt.map(b -> AccountEntityBuilder.buildActivateAccountPerson(b.getId(), response.getName(), privacyMasks.encryptPrivacy(response.getIdCardNo())))
                    .orElse(AccountEntityBuilder.buildInitAccountPerson(record, accountBase, response.getName(), privacyMasks.encryptPrivacy(response.getIdCardNo()), response.getIdCardType()));
            s1 = () -> oldBaseOpt.isPresent() ? accountPersonService.update(person) : accountPersonService.save(person);
        } else {
            preBankCard = oldBaseOpt.map(b -> bankCardService.getOrgUserBankCard(b.getId())).orElse(null);
            // 机构账户，目前仅支持担保机构机构激活
            AccountCompany company = oldBaseOpt.map(b -> AccountEntityBuilder.buildActivateAccountCompany(b.getId(), response.getName(), response.getLegal(), privacyMasks.encryptPrivacy(response.getIdCardNo()), response.getIdCardType(), privacyMasks.encryptPrivacy(response.getMobile()), response.getBankLicense())).orElse(null);
            s1 = () -> accountCompanyService.update(company);
        }
        // 银行卡更新函数
        Supplier<Boolean> s2;
        // 如果是集团账户关联，则不修改银行卡
        if (OpenAccountWayEnum.except(record.getOpenAccountWay(), OpenAccountWayEnum.GROUP_ACCOUNT_CORRELATE, OpenAccountWayEnum.R360_GROUP_ACCOUNT_CORRELATE)) {
            s2 = () -> true;
            // 否则存在修改银行卡，不存在则新增
        } else {
            s2 = openAccountTemplate.getUpdateBankFunction(preBankCard, record.getUserId(), accountBase.getId(), accountType, response.getName(), response.getIdCardNo(), response.getBankcardNo(), response.getBankcode().getCode(), response.getMobile());
        }
        return openAccountTemplate.doHandleSuccessOrder(record, response.getGroupAccountNo(), null, !oldBaseOpt.isPresent(), accountBase, s1, s2);
    }

    /**
     * 开户记录是否过期
     */
    private boolean isRecordExpire(Date lastRequestDate) {
        // 参数有有效时间 10min, 存管网关页面有效时间 10min, 存管网关处理 5min = 25min
        return System.currentTimeMillis() - lastRequestDate.getTime() > 25L * 60L * 1000L;
    }

    @Override
    protected List<UserRoleEnum> getSupportRole() {
        return Collections.EMPTY_LIST;
    }

    @Override
    protected List<OpenAccountWayEnum> getSupportWay() {
        return Collections.EMPTY_LIST;
    }


}
